package classes.classloader;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.lang.reflect.Method;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;

public class Test {
    final static int MAX_SIZE = 1024 * 1024 * 10; // 最大限制10M
    final static int BUFFER_SIZE = 1024 * 1024; // 缓冲区大小
    final static boolean SAVE_GENERATED_FILE = true; // 是否保存生成的文件
    final static String PATH = "/Users/guopanbo/IdeaProjects/understanding-jvm/out/production/understanding-jvm/classes/classloader/";
    final static String CLASS_NAME = "HelloWorld";

    public static void main(String[] args) throws Exception {
        FileInputStream stream = new FileInputStream(PATH + CLASS_NAME + ".class");
        FileChannel channel = stream.getChannel();
        long fileSize = channel.size();
        System.out.println("文件大小：" + fileSize);
        if(fileSize > MAX_SIZE)
            throw new IllegalAccessException("文件超过最大限制");

        ByteBuffer buffer = ByteBuffer.allocate(BUFFER_SIZE);
        byte[] bytes = new byte[(int) fileSize];
        int readBytes, offset = 0;
        while((readBytes = channel.read(buffer)) > 0) {
            buffer.flip();
            buffer.get(bytes, offset, readBytes);
            offset += readBytes;
            buffer.clear();
        }
        channel.close();
        stream.close();

        // 替换utf-8
        bytes = ClassModifier.replaceUtf8(bytes, "java/lang/System", "classes/classloader/MySystem");

        if(SAVE_GENERATED_FILE) {
            String path = PATH + "temp.class";
            FileOutputStream fileOutputStream = new FileOutputStream(path);
            FileChannel channel1 = fileOutputStream.getChannel();
            if(bytes.length > BUFFER_SIZE) {
                int writSize = 0;
                while(writSize < bytes.length) {
                    buffer.clear();
                    buffer.put(bytes, writSize, BUFFER_SIZE);
                    writSize += channel1.write(buffer);
                }
            } else {
                buffer.put(bytes, 0, bytes.length);
                buffer.flip();
                channel1.write(buffer);
            }
            channel1.close();
            fileOutputStream.close();
            System.out.println("生成的class文件已保存, " + path);
        }

        MyClassLoader classLoader = new MyClassLoader();
        Class<HelloWorld> clazz = classLoader.loadBytes("classes.classloader.HelloWorld", bytes);
        Method main = clazz.getDeclaredMethod("main", String[].class);
        main.invoke(null, new String[]{null});
    }
}
